package com.zzy.broker.handler;

import com.zzy.broker.server.message.MqttRawMessage;
import com.zzy.broker.session.ClientSession;
import com.zzy.broker.session.SessionManager;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class SubscribeHandler extends SimpleChannelInboundHandler<MqttRawMessage> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, MqttRawMessage msg) throws Exception {
        // 只处理 SUBSCRIBE 消息 (固定报头高4位 = 8)
        byte messageType = (byte) ((msg.header >> 4) & 0x0F);
        
        if (messageType != 8) {  // 8 = SUBSCRIBE
            // 不是 SUBSCRIBE 消息，传递给下一个 Handler
            ctx.fireChannelRead(msg);
            return;
        }
        
        System.out.println("=== MQTT SUBSCRIBE Message ===");
        System.out.println("Fixed Header: 0x" + String.format("%02X", msg.header));
        System.out.println("Payload Length: " + msg.payload.length);
        System.out.println("Payload (hex): " + bytesToHex(msg.payload));
        
        ByteBuf payload = Unpooled.wrappedBuffer(msg.payload);
        
        try {
            // 1. 读取 Packet Identifier (2字节)
            if (payload.readableBytes() < 2) {
                throw new IllegalArgumentException("Insufficient data for packet identifier");
            }
            int packetId = payload.readUnsignedShort();
            System.out.println("Packet ID: " + packetId);
            
            // 2. MQTT 5.0: 读取 Properties
            // 需要判断是 MQTT 5.0 还是 3.1.1，这里简化处理：尝试读取第一个字节
            // 如果它是小于 128 的值，则可能是 Properties 长度
            int propertiesLength = 0;
            if (payload.isReadable()) {
                payload.markReaderIndex();
                int firstByte = payload.readUnsignedByte();
                
                // 如果第一个字节小于 128，且后面有足够的字节，则认为是 Properties
                // 否则认为是主题长度的高字节
                if (firstByte < 128) {
                    // 这可能是 Properties长度，跳过
                    propertiesLength = firstByte;
                    System.out.println("MQTT 5.0 Properties Length: " + propertiesLength);
                    if (payload.readableBytes() < propertiesLength) {
                        throw new IllegalArgumentException("Insufficient data for properties");
                    }
                    payload.skipBytes(propertiesLength);
                } else {
                    // 不是Properties，重置
                    payload.resetReaderIndex();
                }
            }
            
            // 3. 读取订阅的主题列表
            List<String> topics = new ArrayList<>();
            List<Integer> qosList = new ArrayList<>();
            
            while (payload.isReadable()) {
                if (payload.readableBytes() < 2) break;
                
                int topicLen = payload.readUnsignedShort();
                if (payload.readableBytes() < topicLen) {
                    throw new IllegalArgumentException("Insufficient data for topic");
                }
                
                byte[] topicBytes = new byte[topicLen];
                payload.readBytes(topicBytes);
                String topic = new String(topicBytes, StandardCharsets.UTF_8);
                
                if (payload.readableBytes() < 1) {
                    throw new IllegalArgumentException("Insufficient data for QoS");
                }
                int qos = payload.readUnsignedByte();
                
                topics.add(topic);
                qosList.add(qos);
                
                System.out.println("Subscribe Topic: " + topic + ", QoS: " + qos);
                
                // 保存订阅到会话管理器
                ClientSession session = SessionManager.getInstance().getSessionByChannel(ctx.channel());
                if (session != null) {
                    SessionManager.getInstance().addSubscription(session.getClientId(), topic, qos);
                } else {
                    System.err.println("Session not found for channel: " + ctx.channel());
                }
            }
            
            // 4. 返回 SUBACK
            // SUBACK 格式: [固定报头: 0x90] [剩余长度] [Packet ID] [Return Code(s)]
            // 为每个订阅的主题返回对应的 QoS
            int remainingLength = 2 + topics.size(); // Packet ID (2字节) + Return Codes
            byte[] subackBytes = new byte[2 + remainingLength];
            
            subackBytes[0] = (byte)0x90;              // 固定报头: SUBACK
            subackBytes[1] = (byte)remainingLength;   // 剩余长度
            subackBytes[2] = (byte)(packetId >> 8);   // Packet ID 高字节
            subackBytes[3] = (byte)(packetId & 0xFF); // Packet ID 低字节
            
            // 填充每个主题的 Return Code (0x00 = Success QoS 0, 0x01 = Success QoS 1, 0x02 = Success QoS 2)
            for (int i = 0; i < qosList.size(); i++) {
                subackBytes[4 + i] = qosList.get(i).byteValue();
            }
            
            System.out.println("Sending SUBACK for Packet ID: " + packetId);
            ctx.writeAndFlush(Unpooled.wrappedBuffer(subackBytes));
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            payload.release();
        }
    }
    
    /**
     * 将字节数组转换为十六进制字符串（用于调试）
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        int limit = Math.min(bytes.length, 50); // 只显示前50字节
        for (int i = 0; i < limit; i++) {
            sb.append(String.format("%02X ", bytes[i]));
        }
        if (bytes.length > 50) {
            sb.append("... (" + bytes.length + " bytes total)");
        }
        return sb.toString();
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}
